package parserjc.jaccie;

import java.util.*;

/**
 * This is a automata of a scanner.
 * An automata conatins states.
 *
 * @author Christoph Reich
 * @version 1.00 09.1997
 */
public class Automat {

String ls = "\n"; //System.getProperty("line.separator");

/**
 * The name of the automat.
 */
private String automatName;

/**
 * The list of all automata states.
 */
private Vector stateList = new Vector();

/**
 * The current state number.
 */
private int currentState = 0;

    /**
     * Constructs a automata.
     * @param name the name of the automata
     */
    public Automat(String name) {
        this.automatName = name;
    }

    /**
     * Adds a state to the automata. The order of
     * adding sets the state number.
     * @param state the new state.
     * @see State
     */
    public void add(State state) {
        stateList.addElement(state);
    }

    /**
     * Tests the symbol.
     * @return true if the current state knows the symbol.
     * If the state knows it he returns the follow state.
     * The current state will change to the new follow state
     * of the next not "intern follow state"
     * @see State
     * @param symbol the testing symbol
     */
    public boolean testSymbol(Integer symbol) {
        State state = (State)stateList.elementAt(currentState);
        Integer followState = state.testSymbol(symbol);
        if (followState != null) {
            State nextState = (State)stateList.elementAt(followState.intValue());
            while (nextState.isInternState()) {
               followState = nextState.getFollowState();
               // resets the loop conditions if the loop is an inner loop
               resetInnerStates(nextState.getBorders());
               nextState = (State)stateList.elementAt(followState.intValue());
            }
            currentState = followState.intValue();
            return true;
        }
        else return false;
    }

    /**
     * Reset all states with inner loops. That means the
     * if the "intern state" has a iteration, this iteration will
     * be marked with borders. All "intern states" with an iteration
     * inside the borders have to reset their loop counters.
     * @param borders the string index position of the marked iteration string
     */
    private void resetInnerStates(int borders[]) {
        Enumeration e = stateList.elements();
        while (e.hasMoreElements())
            ((State)e.nextElement()).resetInnerState(borders);
    }

    /**
     * @return the string representation of this state.
     */
    public String getStateText() {
        State state = (State)stateList.elementAt(currentState);
        return state.getStateText();
    }

    /**
     * @return the states of the automat.
     */
    public Vector getStates() {
        return stateList;
    }

    /**
     * @return true if the current state is a final state.
     */
    public boolean isFinalState() {
        State state = (State)stateList.elementAt(currentState);
        return state.isFinalState();
    }

    /**
     * Sets the current state to the state with number zero
     * and calls every state to reset themself.
     */
    public void reset() {
        currentState = 0;
        Enumeration e = stateList.elements();
        while (e.hasMoreElements())
            ((State)e.nextElement()).reset();
    }

    /**
     * @return the name of the automata
     */
    public String getAutomatName() {
        return automatName;
    }

    /**
     * @return a string needed for building a java application
     */
    public String toString() {
        String space = "          ";
        String string = space +"automat = new Automat(\""+automatName+"\");"+ls;
        for (int i=0; i<stateList.size(); i++) {
            string += ((State)stateList.elementAt(i)).toString()+""+ls;
            string += space +"automat.add(state);"+ls;
        }
        return string = string.substring(0,string.length()-1);
    }
} // Automat